<?php

namespace plugin\admin\app\controller;

use app\payment\PayFactory;
use app\services\OrderGroupService;
use app\services\OrderMessageService;
use app\services\OrderService;
use app\services\PropertyService;
use app\services\SystemNoticeService;
use app\services\SystemNoticeTemplateService;
use app\services\WechatMiniProgramShippingService;
use plugin\admin\app\common\Auth;
use plugin\admin\app\common\Util;
use plugin\admin\app\model\Activity;
use plugin\admin\app\model\DealerPropertyLog;
use plugin\admin\app\model\ExpressCompany;
use plugin\admin\app\model\Goods;
use plugin\admin\app\model\GoodsBrand;
use plugin\admin\app\model\OrderGoods;
use plugin\admin\app\model\OrderGroup;
use plugin\admin\app\model\OrderShippingNotice;
use plugin\admin\app\model\SystemNotice;
use plugin\admin\app\model\SystemNoticeTemplate;
use plugin\admin\app\model\User;
use plugin\admin\app\model\UserProfile;
use plugin\admin\app\model\UserPropertyLog;
use support\Db;
use support\Request;
use support\Response;
use plugin\admin\app\model\Order;
use plugin\admin\app\controller\Crud;
use support\exception\BusinessException;

/**
 * 订单列表 
 */
class OrderController extends Crud
{
    
    /**
     * @var Order
     */
    protected $model = null;

    /**
     * 构造函数
     * @return void
     */
    public function __construct()
    {
        $this->model = new Order;
    }
    
    /**
     * 浏览
     * @return Response
     */
    public function index(): Response
    {
        return view('order/index');
    }

    public function express(Request $request)
    {
        try {
            $list = OrderService::expressList($request->get('order_no'));
        } catch (\Exception $e) {
            $list = ['list' => []];
        }

        return view('order/express', [
            'list' => $list
        ]);
    }

    /**
     * 插入
     * @param Request $request
     * @return Response
     * @throws BusinessException
     */
    public function insert(Request $request): Response
    {
        if ($request->method() === 'POST') {
            return parent::insert($request);
        }
        return view('order/insert');
    }

    protected function updateInput(Request $request): array
    {
        $originalData = $request->post();

        $primary_key = $this->model->getKeyName();
        $id = $request->post($primary_key);
        $data = $this->inputFilter($request->post());
        if (!Auth::isSupperAdmin() && $this->dataLimit && !empty($data[$this->dataLimitField])) {
            $admin_id = $data[$this->dataLimitField];
            if (!in_array($admin_id, Auth::getScopeAdminIds(true))) {
                throw new BusinessException('无数据权限');
            }
        }
        $password_filed = 'password';
        if (isset($data[$password_filed])) {
            // 密码为空，则不更新密码
            if ($data[$password_filed] === '') {
                unset($data[$password_filed]);
            } else {
                $data[$password_filed] = Util::passwordHash($data[$password_filed]);
            }
        }

        $data['shipping_time'] = date('Y-m-d H:i:s');
        $data['status'] = Order::STATUS_WAITING_RECEIVE;
        $data['refund_status'] = 0;

        if (empty($originalData['express_company_id'])) {
            throw new \Exception('请选择物流公司');
        }

        if (!($company = ExpressCompany::where('id', $originalData['express_company_id'])->first())) {
            throw new \Exception('不存在的物流公司');
        }

        $data['express_company'] = $company['express_name'];
        $data['express_code'] = $company['key'];

        OrderMessageService::add($data['id']);

        $order = Order::where('id', $data['id'])->first();

        $notice = OrderShippingNotice::where('order_no', $order['order_no'])->where('status', OrderShippingNotice::UN_PROCESS)->first();

        if ($notice) {
            $notice->status = OrderShippingNotice::PROCESS;
            $notice->save();
        }

        unset($data[$primary_key]);
        return [$id, $data];
    }

    public function shippingFee(Request $request)
    {
        if ($request->method() === 'POST') {
            $data = $request->post();

            Order::where('id', $data['id'])->update(['shipping_fee' => $data['shipping_fee'], 'shipping_receive_time' => date('Y-m-d H:i:s')]);

            return $this->json(0, '成功');
        }
        return view('order/shipping_fee');
    }

    /**
     * 更新
     * @param Request $request
     * @return Response
     * @throws BusinessException
    */
    public function update(Request $request): Response
    {
        if ($request->method() === 'POST') {
            [$id, $data] = $this->updateInput($request);
            $this->doUpdate($id, $data);

            $order = Order::find($id);
            WechatMiniProgramShippingService::wechatOrder($order);
            WechatMiniProgramShippingService::wechatNotifyReceive($order);

            $template = SystemNoticeTemplateService::build('order_shipping_notice', [$order['order_no']]);
            SystemNoticeService::sendTemplate($order['user_id'], $template);

            return $this->json(0);
        }
        return view('order/update');
    }

    public function cancel(Request $request): Response
    {
        if ($request->method() === 'POST') {
            $data = $request->post();

            $order = Order::where('id', $data['id'])->first();

            if ($order['cancel_time']) {
                return $this->json(400, '该订单已取消');
            }

            Db::beginTransaction();
            try {
                $order->status = Order::STATUS_CANCEL;
                $order->cancel_reason = '后台作废';
                $order->cancel_time = date('Y-m-d H:i:s');
                $order->admin_cancel_time = date('Y-m-d H:i:s');
                $order->admin_cancel_reason = $data['admin_cancel_reason'] ?? '';
                $order->admin_cancel_type = $data['admin_cancel_type'];
                $order->save();

                if ($order->admin_cancel_type == 2 && $order['pay_time']) {
                    PayFactory::create($order['pay_way'])->setData(['total_amount' => $order['price'], 'user_id' => $order['user_id'], 'source' => UserPropertyLog::ORDER_PAY_BACK, 'order_no' => $order['order_no'], 'order' => $order])->payBack();
                }

                Db::commit();
                return $this->json(0, '成功');

            } catch (\Exception $e) {
                Db::rollBack();
                return $this->json(400, $e->getMessage());
            }

        }
        return view('order/cancel');
    }

    public function show(Request $request): Response
    {
        $orderInfo = Order::find($request->get('id'));
        $orderInfo['pay_way_text'] = UserPropertyLog::getPayWayText($orderInfo['pay_way']);
        $orderGoodsList = OrderGoods::where('order_no', $orderInfo['order_no'])->get()->toArray();

        $goodsIds = array_column($orderGoodsList, 'goods_id');
        $goodsList = Goods::whereIn('id', $goodsIds)->get()->toArray();
        $goodsList = array_combine(
            array_column($goodsList, 'id'),
            array_values($goodsList)
        );
        $brandIds = array_column($goodsList, 'brand_id');
        $brandList = GoodsBrand::whereIn('id', $brandIds)->get()->toArray();
        $brandList = array_combine(
            array_column($brandList, 'id'),
            array_values($brandList)
        );

        foreach ($goodsList as $key=>$goods) {
            $goodsList[$key]['brand'] = $brandList[$goods['brand_id'] ?? 0] ?? [];
        }

        foreach ($orderGoodsList as $key=>$goods) {
            $orderGoodsList[$key]['brand_name'] = $goodsList[$goods['goods_id']]['brand']['name'] ?? '';

            if ($goods['sku']) {
                $sku = json_decode($goods['sku'], true);
            }

            $orderGoodsList[$key]['sku'] = join(',', $sku['sku'] ?? []);
        }

        return view('order/show', [
            'orderInfo' => $orderInfo,
            'orderGoodsList' => $orderGoodsList
        ]);
    }

    protected function formatNormal($items, $total): Response
    {
        $userIds = array_column($items, 'user_id');

        $users = UserProfile::whereIn('user_id', $userIds)->get()->toArray();
        $users = array_combine(
            array_column($users, 'user_id'),
            array_values($users)
        );

        $activityIds = array_column($items, 'activity_id');
        $activities = Activity::whereIn('id', $activityIds)->get()->toArray();
        $activities = array_combine(
            array_column($activities, 'id'),
            array_values($activities)
        );

        foreach ($items as $key=>$item) {
            $items[$key]['pay_way_text'] = UserPropertyLog::getPayWayText($item['pay_way']);
            $items[$key]['status_text'] = Order::getStatusText($item);
            $items[$key]['type_text'] = Order::TYPE_TEXT[$item['type']];
            $items[$key]['user_info'] = $users[$item['user_id']] ?? [];
            $items[$key]['activity'] = $activities[$item['activity_id']] ?? [];
        }

        return json(['code' => 0, 'msg' => 'ok', 'count' => $total, 'data' => $items]);
    }

}
